
#include "CGameApplication.h"
#include "CMapManager.h"

void CMapManager::drawMap(Map *map)
{
	vector<ImagePtr> tempImages = CGameApplication::getInstance()->getGameApp()->getImages();
	std::vector<std::vector<TilePtr>> mapT = map->getMapTiles();

	ImagePtr imgDraw = tempImages.at(1);
	GLfloat sizeTile = map->getSizeTile();

	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

	glEnableClientState( GL_VERTEX_ARRAY );
	glEnableClientState( GL_TEXTURE_COORD_ARRAY );	
	
	glBindTexture( GL_TEXTURE_2D, imgDraw->getTexture() );
	
	for (int i = 0; i < map->getHeight(); i++)
	{
		for (int j = 0; j < map->getWidth(); j++)
		{
			int frameIndex = mapT[i][j]->getTypeTile();
			
			const GLfloat tileX = map->getPosX() + (sizeTile*j);
			const GLfloat tileY = map->getPosY() + (sizeTile*i);

			const GLfloat verts[] = {
				tileX, tileY,
				tileX + sizeTile, tileY,
				tileX + sizeTile, tileY + sizeTile,
				tileX, tileY + sizeTile
			};

			const GLfloat textureWidth = map->getSizeTile() / imgDraw->getWidth();
			const GLfloat textureHeight = map->getSizeTile() / imgDraw->getHeight();
			const int numFramePerRow = imgDraw->getWidth() / map->getSizeTile();
			const GLfloat textureX = (frameIndex % numFramePerRow) * textureWidth;
			const GLfloat textureY = (frameIndex / numFramePerRow + 1) * textureHeight;

			const GLfloat texVerts[] = {
					textureX, textureY,
					textureX + textureWidth, textureY,
					textureX + textureWidth, textureY + textureHeight,
					textureX, textureY + textureHeight
			};
			
			glVertexPointer(2, GL_FLOAT, 0, verts);
			glTexCoordPointer(2, GL_FLOAT, 0, texVerts);
			glDrawArrays(GL_QUADS, 0, 4);

		}
	}		
	
	glDisableClientState( GL_VERTEX_ARRAY );			
	glDisableClientState( GL_TEXTURE_COORD_ARRAY );	
}

void CMapManager::fillMapWithFile(Map *map, std::string filenameMap)
{
	std::vector<std::vector<TilePtr>> mapT = map->getMapTiles();

	for (int i = 0; i < map->getHeight(); i++)
	{
		for (int j = 0; j < map->getWidth(); j++)
		{
			mapT[i][j]->setHasCollision(false);
			mapT[i][j]->setTypeTile(0);
		}
	} 

	std::ifstream dataMap(filenameMap);
	std::string lineData;

	int row = 0;
	while(std::getline(dataMap,lineData))
    {
		for (int j = 0; j < lineData.size(); j++)
		{
			const char a = lineData[j];
			int typeTile = atoi(&a);

			mapT[row][j]->setTypeTile( typeTile );

			if ( typeTile == 5 )
			{
				mapT[row][j]->setHasCollision(true);
			}
		}

		row++;
	}

	dataMap.close();
}

bool CMapManager::checkCollisionWithMap(Map *map, SpritePtr sprite, int movePlayer)
{
	switch(movePlayer)
	{
	case SDLK_UP:
		{
			if ( sprite->getPosY() <= map->getPosY() ||
				getTileByPosition(map, sprite->getPosX(), sprite->getPosY() - map->getSizeTile(), sprite->getSpeedX(), sprite->getSpeedY())->getHasCollision() ){
				return true;
			}
			break;
		}
	case SDLK_DOWN:
		{
			if ( sprite->getPosY() + sprite->getHeight() >= map->getPosY() + ( map->getHeight()*map->getSizeTile() ) ||
				getTileByPosition(map, sprite->getPosX(), sprite->getPosY() + map->getSizeTile(), sprite->getSpeedX(), sprite->getSpeedY()-8.f)->getHasCollision() ){
				return true;
			}
			break;
		}
	case SDLK_LEFT:
		{
			if ( sprite->getPosX() <= map->getPosX() || 
				getTileByPosition(map, sprite->getPosX() - map->getSizeTile(), sprite->getPosY(), sprite->getSpeedX()-8.f, sprite->getSpeedY())->getHasCollision() ) {
				return true;
			}
			break;
		}
	case SDLK_RIGHT:
		{
			if ( sprite->getPosX() + sprite->getWidth() >= map->getPosX() + ( map->getWidth()*map->getSizeTile() ) || 
				getTileByPosition(map, sprite->getPosX() +  map->getSizeTile(), sprite->getPosY(), sprite->getSpeedX(), sprite->getSpeedY())->getHasCollision() ) {
				return true;
			}
			break;
		}
	}
	return false;
}

TilePtr CMapManager::getTileByPosition(Map *map, GLfloat x, GLfloat y, GLfloat offsetX, GLfloat offsetY)
{
	std::vector<std::vector<TilePtr>> mapT = map->getMapTiles();
	int sizeTiles = map->getSizeTile();

	int coordX = (y + offsetY - map->getPosY()) / sizeTiles;
	int coordY = (x + offsetX - map->getPosX()) / sizeTiles;
	
	if (coordY > map->getWidth()-1){
		coordY = map->getWidth()-1;
	}

	if (coordX > map->getHeight()-1){
		coordX = map->getHeight()-1;
	}

	return mapT[coordX][coordY];

}